import datetime
import os
import time
import requests
import json
import threading
from retrying import retry
from enum import Enum

headers = {
    "Host": "jxnu.huitu.zhishulib.com",
    "Connection": "keep-alive",
    "accept": "application/json, text/plain, */*",
    "Origin": "https://jxnu.huitu.zhishulib.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/77.0.3865.56 Safari/537.36 Edg/77.0.235.18",
    "DNT": "1",
    "content-type": "text/plain",
    "Referer": "https://jxnu.huitu.zhishulib.com/",
}


class ROOM(Enum):
    F2_NORTH = 35
    F2_SOUTH = 36
    F3_SOUTH = 31
    F3_NORTH = 37


def get_info():
    try:
        with open('user_info.json', 'r') as fd1:
            user_info = json.load(fd1)
        with open('cookies.json', 'r') as fd2:
            cookies = json.load(fd2)
        return user_info, cookies
    except FileNotFoundError:
        print('您未登录')
        exit(0)


# 登录
def login(name, password):
    url = 'https://jxnu.huitu.zhishulib.com/api/1/login'
    playload = {"code": "8bc9bedd44ddb8bbaa834842080b0095", "login_name": name, "org_id": "142",
                "password": password,
                "str": "qZWvsdYXRNIIbZLD", "_ApplicationId": "lab4", "_ClientVersion": "js_xxx",
                "_InstallationId": "b2e42beb-e60a-7987-3d1b-58ef56ab9bdb", "_JavaScriptKey": "lab4",
                "_SessionToken": "fake"}
    headers["content-type"] = "text/plain"

    try:
        r = requests.post(url, data=json.dumps(playload), headers=headers, timeout=10)
        print("用户:" + playload['login_name'] + ",正在登录.")
        print(r.text)
        r.raise_for_status()
        print('登录成功')
        with open('cookies.json', 'w') as fd1:
            json.dump(r.cookies.get_dict(), fd1, indent=True)
        with open('user_info.json', 'w') as fd2:
            json.dump(r.json(), fd2, indent=True)

    except Exception as e:
        print('登录失败')
        print(e.args)
        exit(0)


# 预定座位
def book_seat(seat_id, begin_time, duration=3):
    url = 'https://jxnu.huitu.zhishulib.com/Seat/Index/bookSeats?LAB_JSON=1'
    user_info, cookies = get_info()
    # 要发送的表单
    playload = {'beginTime': get_tomorrow_timestamp(begin_time), 'duration': duration * 3600, 'seats[0]': seat_id,
                'seatBookers[0]': user_info['id']}
    headers["content-type"] = "application/x-www-form-urlencoded;charset=UTF-8"
    try:
        # 发送表单
        r = request_book_seat(url, playload, cookies)
        # 返回的结果
        result = r.json()
        with open('log.json', 'a+') as fd:
            fd.write('\n//' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + '\n')
            json.dump(result, fd, indent=True)
        if result['DATA']['result'] == 'success':
            print('预定成功')
            return True
        else:
            print('预定失败')
            print(result['DATA']['msg'])
            return False
    except Exception as e:
        print('预定失败')
        print(e.args)
        return False


# 预定座位发生post请求
@retry(stop_max_attempt_number=5)
def request_book_seat(url, playload, cookies, timeout=30):
    r = requests.post(url, data=playload, cookies=cookies, headers=headers, timeout=timeout)
    r.raise_for_status()
    return r


def get_tomorrow_timestamp(clock):
    if 7 <= clock <= 22:
        # 今天日期
        today = datetime.date.today()
        # # for test
        # # 今天开始时间戳
        # today_start_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d')))
        # return today_start_time + int(clock) * 3600

        # 明天时间
        tomorrow = today + datetime.timedelta(days=1)
        # 明天开始时间戳
        tomorrow_start_time = int(time.mktime(time.strptime(str(tomorrow), '%Y-%m-%d')))
        return tomorrow_start_time + int(clock) * 3600
    else:
        print('时间有误')
        exit(0)


# 开始查询座位
def start_search(begin_time, duration, room):
    seat_id, hold_time = search_seat(begin_time, duration, room)
    if seat_id:
        print('{}找到位置{} {}'.format(room, seat_id, hold_time))
        book_seat(seat_id, begin_time, hold_time // 3600)
    else:
        print('{}没有座位'.format(room))
        time.sleep(1)


# 查询座位
def search_seat(begin_time, duration, room):
    url = 'https://jxnu.huitu.zhishulib.com/Seat/Index/searchSeats?LAB_JSON=1'
    _, cookies = get_info()
    playload = {'beginTime': get_tomorrow_timestamp(begin_time), 'duration': duration * 3600, 'num': 1,
                'space_category[category_id]': 591,
                'space_category[content_id]': room.value}
    headers["content-type"] = "application/x-www-form-urlencoded;charset=UTF-8"
    try:
        r = request_search_seat(url, playload, cookies)
        result = r.json()
        with open('log.json', 'a+') as fd:
            fd.write('\n//' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + '\n')
            json.dump(result, fd, indent=True)
        if result['content']['children'][0]['ifHave']:
            if result['content']['children'][0]['ifAdjust']:
                adjust_time = result['content']['children'][1]['adjustTime']
                if adjust_time >= 4 * 3600:
                    # 没有4小时以上的不要
                    return result['data']['bestPairSeats']['seats'][0]['id'], adjust_time
                else:
                    print('有座位但小于4小时:' + result['data']['bestPairSeats']['seats'][0]['id'], adjust_time)
                    # 释放锁定座位
                    # requests.post('https://jxnu.huitu.zhishulib.com/Seat/Index/unlockAllSeats?LAB_JSON=1',
                    # cookies = cookies, headers = headers, timeout = 10)
                    return None, None
            else:
                return result['data']['bestPairSeats']['seats'][0]['id'], duration * 3600
        else:
            return None, None
    except Exception as e:
        print('查询失败')
        print(e.args)
        return None, None


# 查询座位发送post请求
@retry(stop_max_attempt_number=5)
def request_search_seat(url, playload, cookies, timeout=30):
    r = requests.post(url, data=playload, cookies=cookies, headers=headers, timeout=timeout)
    r.raise_for_status()
    return r


if __name__ == '__main__':

    # 加载配置json文件
    type_path = os.path.dirname(__file__)
    json_file = open(os.path.join(type_path, 'login.json'))
    data = json.load(json_file)

    # 获取到配置的信息
    usr = data['usr']
    pwd = data['pwd']
    start_time = data['start_time']
    duration = data['duration']
    print('用户名: ', usr)
    print('密码: ', pwd)
    print('开始时间: ', start_time)
    print('持续时间: ', duration)

    # 瑶湖登录
    login(usr, pwd)

    # 等待执行，每晚10点准时开始
    startTime = datetime.datetime(datetime.datetime.now().year, datetime.datetime.now().month,
                                  datetime.datetime.now().day, 22, 0, 0)

    if datetime.datetime.now() < startTime:
        print('等待执行')
        print("----------------------------")
    while datetime.datetime.now() < startTime:
        time.sleep(1)

    print('开始预定')
    # 通过选定的座位预定
    seats_id = {'27942', '27947', '27951', '27954', '27959', '27964', '27969'}
    for seat_id in seats_id:
        threading.Thread(target=book_seat, args=(seat_id, start_time, duration)).start()
        time.sleep(1)
    time.sleep(20)

    # 随机预定
    for room in ROOM:
        start_search(start_time, duration, ROOM(room))
        time.sleep(1)
